// MIT License
// 开源地址：https://gitee.com/co1024/AbcMvc
// Copyright (c) 2021-2023 1024
// Abc.Mvc=Furion+EF+SqlSugar+Pear layui admin.

using Furion.DynamicApiController;

namespace Abc.Application.ApiAdminServices;

/// <summary>
/// 角色
/// </summary>
[ApiDescriptionSettings("ApiAdmin", Name = "ApiRole")]
[MaApi(  controller: "ApiRole", controllerDescription: "角色", PCode = "API")]
[IgnoreAntiforgeryToken]
public class ApiRoleService : IDynamicApiController
{
    private readonly ILogger<ApiRoleService> _logger;
    private readonly ISqlSugarClient _db;

    public ApiRoleService(ILogger<ApiRoleService> logger
        , ISqlSugarClient db)
    {
        _logger = logger;
        _db = db;
    }

    ///// <summary>
    ///// 刷新缓存
    ///// </summary>
    ///// <returns></returns>
    //public override async Task<List<SysRole>> RefreshCacheAsync()
    //{
    //    var datas = await base.AsQueryable().Includes(r => r.Menus).WithCache().ToListAsync();
    //    return datas;
    //}

    /// <summary>
    /// 新增或更新一条
    /// </summary>
    /// <param name="input"></param>
    /// <returns></returns>
    [MaPermission(name: "新增或更新一条", actions: "InsertOrUpdate")]
    public async Task InsertOrUpdate(ApiRoleInput input)
    {
        if (input.Id > 0)
        {
            var dbentity = await _db.Queryable<SysRole>().FirstAsync(r => r.Id == input.Id);
            input.Adapt(dbentity);
            await _db.UpdateAsync(dbentity);
        }
        else
        {
            var newEntity = await _db.InsertRsIdAsync<SysRole>(input.Adapt<SysRole>());
        }
    }

    /// <summary>
    /// 删除一条
    /// </summary>
    /// <param name="id"></param>
    [MaPermission(name: "删除一条", actions: "Delete")]
    public async Task Delete(long id)
    {
        await _db.DeleteByIdAsync<SysRole>(id);
    }

    /// <summary>
    /// 批量删除
    /// </summary>
    /// <param name="ids">需要删除的数据，多条以英文逗号隔开</param>
    [MaPermission(name: "批量删除", actions: "BatchDelete")]
    public async Task BatchDelete(string ids)
    {
        //这个地方要注意，还没经过测试，不确定是否会触发AOP新增和修改
        await _db.FakeDeleteAsync<SysRole>(ids);
    }

    /// <summary>
    /// 查询一条[跟踪实体]
    /// </summary>
    /// <param name="id"></param>
    [MaPermission(name: "查询一条", actions: "Get")]
    public async Task<ApiRoleOut> Get(long id)
    {
        var dbentity = await _db.GetByIdAsync<SysRole>(id);
        if (dbentity == null) return null;
        return dbentity.Adapt<ApiRoleOut>();
    }

    /// <summary>
    /// 分页查询
    /// </summary>
    /// <param name="searchQuery"></param>
    /// <returns></returns>
    [MaPermission(name: "分页查询", actions: "GetAllByPage")]
    public async Task<PagedList<ApiRoleOut>> GetAllByPageToLayui(ApiRoleQuery searchQuery)
    {
        //var queryable= _roleRepository.DetachedEntities.AsQueryable();
        //if (!string.IsNullOrWhiteSpace(searchQuery.KeyWords))
        //{
        //    var kw = searchQuery.KeyWords.ToLower();
        //    queryable = queryable.Where(o => o.No.Contains(kw));
        //}

        var pageResult = _db.Queryable<SysRole>().OrderByDescending(o => o.Id)
            ;
        return await pageResult.ToPagedListAsync<SysRole, ApiRoleOut>(searchQuery.Page, searchQuery.Limit);
    }

    /// <summary>
    /// 设置角色权限
    /// </summary>
    /// <param name="input">输入role对象</param>
    /// <returns></returns>
    [MaPermission(name: "设置角色权限", actions: "SetRolePermission")]
    public async Task SetRolePermission(ApiRoleInput input)
    {
        //判断角色名称是否存在
        if (input.Id > 0)
        {
            if (_db.Queryable<SysRole>().Any(o => o.Id != input.Id && input.Name == o.Name))
            {
                throw Oops.Bah($"角色名称：【{input.Name}】 以存在");
            }
        }
        else
        {
            if (_db.Queryable<SysRole>().Any(o => input.Name == o.Name))
            {
                throw Oops.Bah($"角色名称：【{input.Name}】 以存在");
            }
        }

        var dbrole = await _db.Queryable<SysRole>().Includes(o => o.RoleMenus).FirstAsync(o => o.Id == input.Id);
        if (dbrole == null)
        {
            dbrole = input.Adapt<SysRole>();
            //dbrole.Menus = new List<SysMenu>();
            //dbrole.Menus = new List<SysMenu>();

            input.Id = await _db.InsertRsIdAsync<SysRole>(dbrole);
            //新增后，查询出来
            dbrole = await _db.Queryable<SysRole>().Includes(o => o.RoleMenus).FirstAsync(o => o.Id == input.Id);
        }
        else
        {
            input.Adapt(dbrole);
            await _db.UpdateAsync(dbrole);
        }

        //获取全部菜单数据
        var dbmenus = await _db.Queryable<SysMenu>().ToListAsync();
        var permissions = input.Permissionstrs.ToList(new char[] { ',' });

        #region 从数据库移除删除的权限

        {
            var roleMenuIds = dbrole.RoleMenus.Select(o => o.MenuId).ToList();
            var roleMenus = await _db.Queryable<SysMenu>().Where(o => roleMenuIds.Contains(o.Id)).ToListAsync();
            //需要删除的角色菜单
            var removeRoleMenus = new List<dynamic>();
            //foreach (var permissionid in roleMenus.Select(o => o.Code).ToList())
            //{
            //    var permission = roleMenus.First(o => o.Code.Trim().ToLower() == permissionid.Trim().ToLower());
            //    if (permissions.All(o => o != permissionid)) removeRoleMenus.Add(permission);
            //}
            foreach (var menu in roleMenus)
            {
                if (permissions.All(o => o != menu.Code))
                {
                    var rolemenu = dbrole.RoleMenus.FirstOrDefault(o => o.MenuId == menu.Id && o.RoleId == dbrole.Id);
                    removeRoleMenus.Add(rolemenu.Id);
                    //removeMenus.Add(menu);
                }
            }
            _db.DeleteByIds<SysRoleMenu>(removeRoleMenus);
        }

        #endregion 从数据库移除删除的权限

        #region 新增权限

        {
            var roleMenus = new List<SysRoleMenu>();
            foreach (var permissionid in permissions)
            {
                var dbmenu = dbmenus.FirstOrDefault(o => o.Code.Trim().ToLower() == permissionid.Trim().ToLower());
                if (dbmenu == null) continue;
                //如果还有上级，则跳过，只关联末尾节点
                if (dbmenus.Any(o => !string.IsNullOrWhiteSpace(o.PCode) && o.PCode.Trim().ToLower() == dbmenu.Code.Trim().ToLower())) continue;
                if (dbrole.RoleMenus.Any(o => o.MenuId == dbmenu.Id)) continue;//以存在跳过
                roleMenus.Add(new SysRoleMenu() { MenuId = dbmenu.Id, RoleId = input.Id.Value });
            }

            await _db.InsertRsIdAsync<SysRoleMenu>(roleMenus);
        }

        #endregion 新增权限
    }

    /// <summary>
    /// 获取角色 权限 Dtree 树
    /// </summary>
    /// <param name="roleid"></param>
    /// <param name="area">区域</param>
    /// <returns></returns>
    [MaPermission(name: "获取角色 权限 Dtree 树", actions: "GetRoleDtreeCheck")]
    public async Task<Dtree> GetRoleDtreeCheck(long roleid = 0, string area = "ApiAdmin")
    {
        SysRole role = null;
        if (roleid > 0)
        {
            //var roleentities = await _db.GetCacheListAsync();
            role = await _db.Queryable<SysRole>().Includes(o => o.RoleMenus).FirstAsync(o => o.Id == roleid);
        }
        //获取区域菜单
        var menus = await _db.Queryable<SysMenu>().Where(o => o.Area != null && o.Area.ToLower() == area.ToLower()).ToListAsync();
        //只查询显示可用且可显示的菜单
        menus = menus.Where(o => o.IsEnable == true).ToList();

        //var rolemenus = role?.Menus?.ToList() ?? new List<SysMenu>();
        //var dtreeitems = GetDtreeCheckItems(menus, rolePermissions);

        var roleMenus = new List<SysMenu>();
        if (role != null && role.Id > 0)
        {
            var roleMenuIds = role.RoleMenus.Select(o => o.MenuId).ToList();
            roleMenus = await _db.Queryable<SysMenu>().Where(o => roleMenuIds.Contains(o.Id)).ToListAsync();
        }

        var alldatas = menus
            .Where(o => o.Area == "ApiAdmin")
            .Select(o => new DtreeEntity { id = o.Code, pid = o.PCode, name = o.Name, sort = o.Sort });
        var selectdatas = roleMenus.Select(o => new DtreeEntity { id = o.Code, pid = o.PCode, name = o.Name, sort = o.Sort });

        var dtree = alldatas.GetDtreeCheck(pid: "ApiAdmin", selectdatas); ;
        return dtree;
    }

    /// <summary>
    /// 设置状态
    /// </summary>
    /// <param name="id"></param>
    /// <param name="state"></param>
    /// <param name="field">字段名</param>
    /// <returns></returns>
    [MaPermission(name: "设置状态", actions: "SetState")]
    public async Task SetState(long id, bool state, string field)
    {
        var result = await _db.SetStateByIdAsync<SysRole>(id, state, field);
    }

    /// <summary>
    /// 查询所有
    /// </summary>
    /// <returns></returns>
    [MaPermission(name: "查询所有", actions: "GetAll")]
    public async Task<List<ApiRoleOut>> GetAll()
    {
        var entities = await _db.Queryable<SysRole>().ToListAsync();

        return entities.Adapt<List<ApiRoleOut>>();
    }
}